package org.dromara.netbar.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import org.dromara.common.core.utils.AssertUtils;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.netbar.domain.NetbarGiftPack;
import org.dromara.netbar.domain.NetbarGiftPackLog;
import org.dromara.netbar.domain.vo.*;
import org.dromara.netbar.mapper.NetbarGiftPackItemMapper;
import org.dromara.netbar.mapper.NetbarGiftPackLogMapper;
import org.dromara.netbar.service.INetbarCouponMemberService;
import org.dromara.netbar.service.INetbarGiftPackLogService;
import org.dromara.netbar.service.INetbarGiftPackService;
import org.springframework.stereotype.Service;
import org.dromara.netbar.domain.bo.NetbarAutoGrantBo;
import org.dromara.netbar.domain.NetbarAutoGrant;
import org.dromara.netbar.mapper.NetbarAutoGrantMapper;
import org.dromara.netbar.service.INetbarAutoGrantService;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 自动发放策略Service业务层处理
 *
 * @author Lion Li
 * @date 2025-07-10
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class NetbarAutoGrantServiceImpl implements INetbarAutoGrantService {

    private final NetbarAutoGrantMapper baseMapper;
    private final NetbarGiftPackItemMapper giftPackItemMapper;
    private final NetbarGiftPackLogMapper giftPackLogMapper;
    private final INetbarGiftPackService giftPackService;
    private final INetbarCouponMemberService couponMemberService;
    private final INetbarGiftPackLogService giftPackLogService;

    /**
     * 查询自动发放策略
     *
     * @param autoGrantId 主键
     * @return 自动发放策略
     */
    @Override
    public NetbarAutoGrantVo queryById(Long autoGrantId){
        return baseMapper.selectVoById(autoGrantId);
    }

    /**
     * 分页查询自动发放策略列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 自动发放策略分页列表
     */
    @Override
    public TableDataInfo<NetbarAutoGrantVo> queryPageList(NetbarAutoGrantBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<NetbarAutoGrant> lqw = buildQueryWrapper(bo);
        List<NetbarGiftPackVo> netbarGiftPackVos = giftPackService.listPackNameAndId();
        Page<NetbarAutoGrantVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Optional<NetbarGiftPackVo> any;
        for (NetbarAutoGrantVo record : result.getRecords()) {
            any = netbarGiftPackVos.stream().filter(n -> n.getPackId().equals(record.getGiftPackId())).findAny();
            record.setGiftPack(any.orElse(null));
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的自动发放策略列表
     *
     * @param bo 查询条件
     * @return 自动发放策略列表
     */
    @Override
    public List<NetbarAutoGrantVo> queryList(NetbarAutoGrantBo bo) {
        LambdaQueryWrapper<NetbarAutoGrant> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<NetbarAutoGrant> buildQueryWrapper(NetbarAutoGrantBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<NetbarAutoGrant> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(NetbarAutoGrant::getAutoGrantId);
        lqw.like(StringUtils.isNotBlank(bo.getGrantName()), NetbarAutoGrant::getGrantName, bo.getGrantName());
        return lqw;
    }

    /**
     * 新增自动发放策略
     *
     * @param bo 自动发放策略
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(NetbarAutoGrantBo bo) {
        validEntityBeforeSave(bo);
        NetbarAutoGrant add = MapstructUtils.convert(bo, NetbarAutoGrant.class);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setAutoGrantId(add.getAutoGrantId());
        }
        return flag;
    }

    /**
     * 修改自动发放策略
     *
     * @param bo 自动发放策略
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(NetbarAutoGrantBo bo) {
        validEntityBeforeSave(bo);
        NetbarAutoGrant update = MapstructUtils.convert(bo, NetbarAutoGrant.class);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(NetbarAutoGrantBo entity){
        //TODO 做一些数据校验,如唯一约束
        List<NetbarGiftPackVo> netbarGiftPackVos = giftPackService.listPackNameAndId();
        AssertUtils.notNull(entity.getGrantName(), "请输入发放名称");
        AssertUtils.notNull(entity.getGrantType(), "请选择发放类型");
        AssertUtils.notNull(entity.getGiftPackId(), "请选择关联礼包");
        AssertUtils.notNull(entity.getMethodCount(), "请输入可领次数限制（0=无限次）");
        AssertUtils.notNull(entity.getMinRechargeAmount(), "请输入单次充值最低金额（>=此金额触发）");
        AssertUtils.isTrue(netbarGiftPackVos.stream().anyMatch(n -> n.getPackId()
                .equals(entity.getGiftPackId())), "该礼包不存在");
        long l = baseMapper.selectCount(new LambdaQueryWrapper<NetbarAutoGrant>().ne(null !=  entity.getAutoGrantId(), NetbarAutoGrant::getAutoGrantId, entity.getAutoGrantId()).eq(NetbarAutoGrant::getGiftPackId, entity.getGiftPackId()));
        AssertUtils.isTrue(l == 0, "该礼包已存在自动发放策略");
    }

    /**
     * 校验并批量删除自动发放策略信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public List<NetbarAutoGrantVo> listGiftPackByBalanceAndMemberId(Long amount, String tenantId, Long memberId) {
        List<NetbarAutoGrantVo> results = new ArrayList<>();
        // 1、先获取有什么自动发放礼包
        List<NetbarAutoGrantVo> autoGrants = baseMapper.selectAutoGrant(tenantId, amount);
        // 2、判断哪个礼包满足发放
        // 3、获取用户发放过的礼包，判断哪个礼包不能发放
        LambdaQueryWrapper<NetbarGiftPackLog> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(NetbarGiftPackLog::getPackLogId, NetbarGiftPackLog::getMemberId, NetbarGiftPackLog::getPackId, NetbarGiftPackLog::getSendTime);
        lambdaQueryWrapper.eq(NetbarGiftPackLog::getMemberId, memberId);
        List<NetbarGiftPackLogVo> giftPackLogs = giftPackLogMapper.selectVoList(lambdaQueryWrapper);
        if (CollectionUtil.isNotEmpty(autoGrants)) {
            for (NetbarAutoGrantVo autoGrant : autoGrants) {
                if (autoGrant.getMethodCount() == 0 || autoGrant.getMethodCount() > giftPackLogs.stream().filter(l->l.getPackId().equals(autoGrant.getGiftPackId())).count()) {
                    results.add(autoGrant);
                }
            }
        }
        return results;
    }

    @Override
    public void sendGiftPack(List<NetbarAutoGrantVo> netbarAutoGrantVos, NetbarMemberVo netbarMemberVo) {
        // 1. 参数校验（防御式编程）
        if (CollectionUtil.isEmpty(netbarAutoGrantVos) || netbarMemberVo == null || netbarMemberVo.getMemberId() == null) {
            log.warn("参数校验失败：netbarAutoGrantVos或memberId为空");
            return;
        }

        // 2. 提取会员ID（避免多次调用get方法）
        final Long memberId = netbarMemberVo.getMemberId();

        // 3. 提取礼包ID列表（使用Stream去重）
        List<Long> giftPackIdList = netbarAutoGrantVos.stream()
            .map(NetbarAutoGrantVo::getGiftPackId)
            .distinct()  // 去重避免重复查询
            .collect(Collectors.toList());

        // 4. 批量查询礼包明细（减少数据库交互）
        List<NetbarGiftPackItemVo> netbarGiftPackItemVos = giftPackItemMapper.queryListByPackIds(giftPackIdList);

        if (CollectionUtil.isEmpty(netbarGiftPackItemVos)) {
            log.warn("未查询到礼包明细数据，礼包IDs: {}", giftPackIdList);
            return;
        }

        // 5. 聚合卡券数量（使用merge方法优化计数）
        Map<Long, Long> couponNumberMap = new HashMap<>();
        List<Long> gqGiftPackIdList = netbarGiftPackItemVos.stream().filter(n -> "过期".equals(n.getCouponStatus())).map(NetbarGiftPackItemVo::getPackId).toList();
        // 如果礼包里有卡券过期，则礼包失效
        netbarGiftPackItemVos.stream().filter(n->!gqGiftPackIdList.contains(n.getPackId())).forEach(item ->
            couponNumberMap.merge(
                item.getCouponId(),
                item.getCouponCount(),
                Long::sum  // 相同couponId的数量累加
            )
        );
        // 6. 分发卡券（添加事务注解建议）
        try {
            couponMemberService.saveCouponMemberByMap(couponNumberMap, List.of(memberId));
            // 7、添加发放次数
            giftPackLogService.saveSendLogs(giftPackIdList, List.of(memberId), new Date());
            log.info("会员[{}]卡券分发成功，券种数量: {}", memberId, couponNumberMap.size());
        } catch (Exception e) {
            log.error("会员[{}]卡券分发失败，原因: {}", memberId, e.getMessage());
        }
    }

}
